﻿using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using p2pMessaging.Contracts;
using p2pMessaging.Interfaces;

namespace p2pMessaging.Tests
{
	[TestFixture]
	public class CryptographyServiceTest
	{
		private ICryptographyService myCryptographyService;

		[SetUp]
		public void SetUp()
		{
			myCryptographyService = ServiceLocator.Get<ICryptographyService>();
		}

		[Test]
		public void EncryptAndDecrypt()
		{
			string password = "pw";
			byte[] plain = Encoding.UTF8.GetBytes("Hello World");
			byte[] cipher = myCryptographyService.Encrypt(plain, CryptographyServiceAlgorithm.TripleDES, password);
			byte[] newPlain = myCryptographyService.Decrypt(cipher, CryptographyServiceAlgorithm.TripleDES, password);
			string result = Encoding.UTF8.GetString(newPlain);
			
			Assert.AreEqual("Hello World", result);
		}

		[Test]
		public void EncryptWithAll()
		{
			string password = "somePassword";
			byte[] plain = Encoding.UTF8.GetBytes("Hello World");
			byte[] cipherDes = myCryptographyService.Encrypt(plain, CryptographyServiceAlgorithm.DES, password);
			byte[] cipherRc2 = myCryptographyService.Encrypt(plain, CryptographyServiceAlgorithm.RC2, password);
			byte[] cipherRijndael = myCryptographyService.Encrypt(plain, CryptographyServiceAlgorithm.RijnDael, password);
			byte[] cipherTripleDes = myCryptographyService.Encrypt(plain, CryptographyServiceAlgorithm.TripleDES, password);

			Assert.AreNotEqual(cipherDes, cipherRc2);
			Assert.AreNotEqual(cipherDes, cipherRijndael);
			Assert.AreNotEqual(cipherDes, cipherTripleDes);
			Assert.AreNotEqual(cipherRc2, cipherRijndael);
			Assert.AreNotEqual(cipherRc2, cipherTripleDes);
			Assert.AreNotEqual(cipherRijndael, cipherTripleDes);
		}

		[Test]
		public void EncryptWithDifferentPasswords()
		{
			byte[] plain = Encoding.UTF8.GetBytes("Hello World");
			byte[] cipher1 = myCryptographyService.Encrypt(plain, CryptographyServiceAlgorithm.DES, "abcdefg");
			byte[] cipher2 = myCryptographyService.Encrypt(plain, CryptographyServiceAlgorithm.DES, "bcdefgh");
			byte[] cipher3 = myCryptographyService.Encrypt(plain, CryptographyServiceAlgorithm.DES, "cdefghi");
			byte[] cipher4 = myCryptographyService.Encrypt(plain, CryptographyServiceAlgorithm.DES, "defghij");

			Assert.AreNotEqual(cipher1, cipher2);
			Assert.AreNotEqual(cipher1, cipher3);
			Assert.AreNotEqual(cipher1, cipher4);
			Assert.AreNotEqual(cipher2, cipher3);
			Assert.AreNotEqual(cipher2, cipher4);
			Assert.AreNotEqual(cipher3, cipher4);
		}

		[Test]
		public void EncryptAlwaysTheSame()
		{
			byte[] plain = Encoding.UTF8.GetBytes("Some text to encode.");

			List<byte[]> results = new List<byte[]>();
			for (int i = 0; i < 4; i++)
			{
				results.Add(myCryptographyService.Encrypt(plain, CryptographyServiceAlgorithm.RijnDael, "a password"));
			}
			
			Assert.AreEqual(results[0], results[1]);
			Assert.AreEqual(results[0], results[2]);
			Assert.AreEqual(results[0], results[3]);
			Assert.AreEqual(results[1], results[2]);
			Assert.AreEqual(results[1], results[3]);
			Assert.AreEqual(results[2], results[3]);
		}
	}
}
